package com.biodiv.miracle.web.handler;

import com.alibaba.fastjson2.JSON;
import com.biodiv.miracle.support.utils.ResourceUtils;
import com.biodiv.miracle.web.support.annotation.RequestBody;
import com.biodiv.miracle.web.support.annotation.RequestParam;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

/**
 * @Author: tianquan
 * @CreateTime: 2025-05-26  16:38
 * @Description: controller方法封装类
 */
public class HandlerMethod {

    private final Object bean;

    private final Method method;

    private final Parameter[] parameters;

    public HandlerMethod(Object bean, Method method, Parameter[] parameters) {
        this.bean = bean;
        this.method = method;
        this.parameters = parameters;
    }

    public Object getBean() {
        return bean;
    }

    public Object invoke(HttpServletRequest request) {
        try {
            Object[] args = new Object[parameters.length];
            // 解析参数
            Map<String, String[]> parameterMap = request.getParameterMap();
            for (int i = 0; i < parameters.length; i++) {
                // 处理请求url上的参数
                Parameter parameter = parameters[i];
                String parameterName;
                Object parameterValue = null;
                RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
                if (requestParam != null) {
                    parameterName = requestParam.value();
                    // 获取参数值
                    String[] parameterValues = parameterMap.get(parameterName);
                    if (parameterValues == null) {
                        // 获取默认值
                        parameterValue = requestParam.defaultValue();
                    } else if (parameterValues.length == 1) {
                        parameterValue = parameterValues[0];
                    } else {
                        // 获取多个值
                        parameterValue = new ArrayList<>(Arrays.asList(parameterValues));
                    }
                    if (!requestParam.required() && parameterValue == null) {
                        throw new RuntimeException("参数 " + parameterName + " 不能为空");
                    }
                    parameterValue = converterParam(parameter, parameterValue);
                }

                // 处理请求体参数
                if (!"GET".equals(request.getMethod())) {
                    RequestBody requestBody = parameter.getAnnotation(RequestBody.class);
                    if (requestBody != null){
                        ServletInputStream inputStream = request.getInputStream();
                        String body = ResourceUtils.convert(inputStream);
                        parameterValue = JSON.parseObject(body, parameter.getType());
                    }
                }

                // 封装参数
                args[i] = parameterValue;
            }
            // 执行controller对应的方法
            return method.invoke(bean, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Object converterParam(Parameter parameter, Object parameterValue) {
        // 判断参数是否为基本类型
        Class<?> parameterType = parameter.getType();
        if (parameterValue != null) {
            // int
            if (parameterType == int.class) {
                parameterValue = Integer.parseInt((String) parameterValue);
            } else if (parameterType == Integer.class) {
                parameterValue = Integer.parseInt((String) parameterValue);
            }
            // long
            else if (parameterType == long.class) {
                parameterValue = Long.parseLong((String) parameterValue);
            } else if (parameterType == Long.class) {
                parameterValue = Long.parseLong((String) parameterValue);
            }
            // float
            else if (parameterType == float.class) {
                parameterValue = Float.parseFloat((String) parameterValue);
            } else if (parameterType == Float.class) {
                parameterValue = Float.parseFloat((String) parameterValue);
            }
            // double
            else if (parameterType == double.class) {
                parameterValue = Double.parseDouble((String) parameterValue);
            } else if (parameterType == Double.class) {
                parameterValue = Double.parseDouble((String) parameterValue);
            }
            // boolean
            else if (parameterType == boolean.class) {
                parameterValue = Boolean.parseBoolean((String) parameterValue);
            } else if (parameterType == Boolean.class) {
                parameterValue = Boolean.parseBoolean((String) parameterValue);
            }
            // string
            else if (parameterType == char.class) {
                parameterValue = ((String) parameterValue).charAt(0);
            } else if (parameterType == String.class) {
                parameterValue = parameterValue.toString();
            }
            // byte
            else if (parameterType == byte.class) {
                parameterValue = Byte.parseByte((String) parameterValue);
            } else if (parameterType == Byte.class) {
                parameterValue = Byte.parseByte((String) parameterValue);
            }
            // short
            else if (parameterType == short.class) {
                parameterValue = Short.parseShort((String) parameterValue);
            } else if (parameterType == Short.class) {
                parameterValue = Short.parseShort((String) parameterValue);
            }
            // json
            else {
                parameterValue = JSON.parseObject(parameterValue.toString(), parameterType);
            }
        }
        return parameterValue;
    }

    public Method getMethod() {
        return method;
    }

    public Object[] getParameters() {
        return parameters;
    }
}
